/*
 *      Copyright 2012-2013 Battams, Derek
 *       
 *       Licensed under the Apache License, Version 2.0 (the "License");
 *       you may not use this file except in compliance with the License.
 *       You may obtain a copy of the License at
 *
 *          http://www.apache.org/licenses/LICENSE-2.0
 *
 *       Unless required by applicable law or agreed to in writing, software
 *       distributed under the License is distributed on an "AS IS" BASIS,
 *       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *       See the License for the specific language governing permissions and
 *       limitations under the License.
 */
package org.schedulesdirect.grabber;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import java.util.Date;

import org.apache.commons.io.IOUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.schedulesdirect.api.ApiResponse;
import org.schedulesdirect.api.Config;

import de.schlichtherle.truezip.file.TFile;

/**
 * Various utility methods
 * @author Derek Battams &lt;derek@battams.ca&gt;
 *
 */
public final class Utils {
	
	/**
	 * Calculate the end date of an Airing
	 * @param src An Airing object as JSON
	 * @return The Date when the given airing is scheduled to end
	 * @throws JSONException If the src is not valid
	 */
	static public Date getEndDateForAiring(JSONObject src) throws JSONException {
		try {
			return new Date(Config.get().getDateTimeFormat().parse(src.getString("airDateTime")).getTime() + (src.getLong("duration") * 1000L));
		} catch(ParseException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * Write an entry to the given VFS
	 * @param vfs The VFS to write to
	 * @param entry The name of the entry to write in the VFS
	 * @param data The data to be written
	 * @throws IOException On any IO error
	 */
	static public void writeVfsEntry(File vfs, String entry, String data) throws IOException {
		InputStream ins = new ByteArrayInputStream(data.getBytes("UTF-8"));
		writeVfsEntry(vfs, entry, ins, null);
	}
	
	/**
	 * Write binary data to the given VFS
	 * @param vfs The VFS to write to
	 * @param entry The name of the entry to write in the VFS
	 * @param data The data to be written
	 * @param lastModified If not null, sets the last modified date of the file in the VFS to this value
	 * @throws IOException On any IO error
	 */
	static public void writeVfsEntry(File vfs, String entry, InputStream data, Date lastModified) throws IOException {
		TFile dest = new TFile(vfs, entry);
		if(lastModified != null) {
			File f = null;
			try {
				f = File.createTempFile("sdjson_", ".logo");
				OutputStream outs = new FileOutputStream(f);
				IOUtils.copy(data, outs);
				outs.close();
				f.setLastModified(lastModified.getTime());
				TFile.cp_p(f, dest);
			} finally {
				if(f != null) f.delete();
			}
		} else
			TFile.cp(data, dest);
	}
	
	/**
	 * Read an entry from a VFS
	 * @param vfs The VFS to read from
	 * @param path The entry to read in the VFS
	 * @return The data stored in the given VFS entry or null if it does not exist
	 */
	static public String readVfsEntry(File vfs, String path) {
		return readVfsEntry(new TFile(vfs, path));
	}
	
	/**
	 * Read an entry from a VFS
	 * @param entry The entry to be read
	 * @return The data read or null if the entry is invalid
	 */
	static public String readVfsEntry(TFile entry) {
		try {
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			TFile.cp(entry, os);
			return os.toString("UTF-8");
		} catch (IOException e) {
			return null;
		}		
	}
	
	/**
	 * Return an entry from the VFS as an InputStream; caller must close the stream when done
	 * @param vfs The VFS to read from
	 * @param path The path of the VFS to be read
	 * @return An InputStream containing the entry's data or null if no such entry exists or an error occured
	 */
	static public InputStream readVfsData(File vfs, String path) {
		return readVfsData(new TFile(vfs, path));
	}
	
	/**
	 * Return an entry from the VFS as an InputStream; caller must close the stream when done
	 * @param entry The VFS entry to be read
	 * @return An InputStream containing the entry's data or null if no such entry exists or an error occured
	 */
	static public InputStream readVfsData(TFile entry) {
		ByteArrayOutputStream os = null;
		try {
			os = new ByteArrayOutputStream();
			TFile.cp(entry,  os);
			return new ByteArrayInputStream(os.toByteArray());
		} catch(IOException e) {
			return null;
		} finally {
			if(os != null) try { os.close(); } catch(IOException e) {}
		}
	}
	
	/**
	 * Determine if a response from the SD server is an error response or not
	 * @param resp The response to inspect
	 * @return True if the response is an error response or false otherwise
	 */
	static public boolean isErrorResponse(JSONObject resp) {
		return resp.has("code") && resp.optInt("code", -1) != ApiResponse.OK;
	}

	/**
	 * Get the last modified date of an entry from the VFS or null if the entry does not exist
	 * @param vfs The VFS to inspect
	 * @param path The path to check for
	 * @return The Date it was last modified or null if the entry does not exist
	 */
	static public Date getVfsEntryDate(File vfs, String path) {
		TFile entry = new TFile(vfs, path);
		return entry.exists() ? new Date(entry.lastModified()) : null;
	}

	private Utils() {}
}
